package com.websem.server;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.websem.client.services.FilmService;

import fr.inria.acacia.corese.api.IDatatype;
import fr.inria.acacia.corese.exceptions.EngineException;
import fr.inria.edelweiss.kgram.core.Mapping;
import fr.inria.edelweiss.kgram.core.Mappings;

/**
 * @author haifa
 * @author issam
 */
public class FilmServiceImpl extends RemoteServiceServlet implements
		FilmService {

	private static final long serialVersionUID = 6230086399043420502L;

	WebSemanticService webSemanticService = new WebSemanticService(
			"resources/cinema.rdf", "resources/cinema.rdfs");

	@Override
	public List<HashMap<String, String>> getFilms() {
		List<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();

		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT * WHERE {  ?x cinema:name ?name ?x cinema:duration ?duration "
				+ "?x cinema:country ?country ?x cinema:rating ?rating ?x cinema:releaseYear ?year "
				+ "?x cinema:releaseDate ?date ?x cinema:realisedBy ?director "
				+ "?director cinema:name ?directorName ?x cinema:producedBy ?producer ?producer cinema:name ?producerName"
				+ "?x cinema:affiche ?affiche ?x cinema:synopsis ?synopsis ?x rdf:type cinema:Film }";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				getFilmDescription(result, m);
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<String> getGenre() {
		List<String> result = new ArrayList<String>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT DISTINCT ?genre WHERE { ?x cinema:genre ?genre ?x rdf:type cinema:Film}";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				IDatatype dt = (IDatatype) m.getValue("?genre");
				result.add(dt.getLabel());
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<String> getPrizes() {
		List<String> result = new ArrayList<String>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT DISTINCT ?y WHERE {?x cinema:name ?y ?x rdf:type cinema:Prize }";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				IDatatype dt = (IDatatype) m.getValue("?y");
				result.add(dt.getLabel());
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<String> getCountry() {
		List<String> result = new ArrayList<String>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT DISTINCT ?country WHERE { ?x cinema:country ?country ?x rdf:type cinema:Film}";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				IDatatype dt = (IDatatype) m.getValue("?country");
				result.add(dt.getLabel());
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<String> getLanguage() {
		List<String> result = new ArrayList<String>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT DISTINCT ?language WHERE { ?x cinema:language ?language ?x rdf:type cinema:Film}";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				IDatatype dt = (IDatatype) m.getValue("?language");
				result.add(dt.getLabel());
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<String> getVersion() {
		List<String> result = new ArrayList<String>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT DISTINCT ?version WHERE { ?x cinema:version ?version ?x rdf:type cinema:Film}";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				IDatatype dt = (IDatatype) m.getValue("?version");
				result.add(dt.getLabel());
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<HashMap<String, String>> getComingSoonFilm() {
		List<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
		// System.out.println(System.currentTimeMillis());
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT * WHERE { ?x cinema:name ?name ?x cinema:duration ?duration "
				+ "?x cinema:country ?country ?x cinema:rating ?rating ?x cinema:releaseYear ?year "
				+ "?x cinema:releaseDate ?date ?x cinema:realisedBy ?director ?x cinema:version ?version"
				+ "?director cinema:name ?directorName ?x cinema:producedBy ?producer ?producer cinema:name ?producerName"
				+ "?x cinema:affiche ?affiche ?x cinema:synopsis ?synopsis ?x rdf:type cinema:Film"
				+ " FILTER (xsd:date(?date) >= '2013-02-08'^^xsd:date)}";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				getFilmDescription(result, m);
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<HashMap<String, String>> getFilmByGenre(String genre) {
		List<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT * WHERE { ?x cinema:genre "
				+ "\""
				+ genre
				+ "\""
				+ " "
				+ "?x cinema:name ?name ?x cinema:duration ?duration "
				+ "?x cinema:country ?country ?x cinema:rating ?rating ?x cinema:version ?version ?x cinema:releaseYear ?year "
				+ "?x cinema:releaseDate ?date ?x cinema:realisedBy ?director "
				+ "?director cinema:name ?directorName ?x cinema:producedBy ?producer ?producer cinema:name ?producerName"
				+ "?x cinema:affiche ?affiche ?x cinema:synopsis ?synopsis ?x rdf:type cinema:Film}";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				getFilmDescription(result, m);
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<HashMap<String, String>> getFilmByCountry(String country) {
		List<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT * WHERE { ?x cinema:country "
				+ "\""
				+ country
				+ "\""
				+ " "
				+ "?x cinema:name ?name ?x cinema:duration ?duration ?x cinema:version ?version"
				+ "?x cinema:country ?country ?x cinema:rating ?rating ?x cinema:releaseYear ?year "
				+ "?x cinema:releaseDate ?date ?x cinema:realisedBy ?director "
				+ "?director cinema:name ?directorName ?x cinema:producedBy ?producer ?producer cinema:name ?producerName"
				+ "?x cinema:affiche ?affiche ?x cinema:synopsis ?synopsis ?x rdf:type cinema:Film}";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				getFilmDescription(result, m);
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<HashMap<String, String>> getFilmByLanguage(String language) {
		List<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT * WHERE { ?x cinema:language "
				+ "\""
				+ language
				+ "\""
				+ " "
				+ "?x cinema:name ?name ?x cinema:duration ?duration ?x cinema:version ?version "
				+ "?x cinema:country ?country ?x cinema:rating ?rating ?x cinema:releaseYear ?year "
				+ "?x cinema:releaseDate ?date ?x cinema:realisedBy ?director "
				+ "?director cinema:name ?directorName ?x cinema:producedBy ?producer ?producer cinema:name ?producerName"
				+ "?x cinema:affiche ?affiche ?x cinema:synopsis ?synopsis ?x rdf:type cinema:Film}";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				getFilmDescription(result, m);
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<HashMap<String, String>> getFilmByDate(String date) {
		List<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT * WHERE { ?x cinema:releaseYear "
				+ "\""
				+ date
				+ "\""
				+ " "
				+ "?x cinema:name ?name ?x cinema:duration ?duration ?x cinema:version ?version"
				+ "?x cinema:country ?country ?x cinema:rating ?rating ?x cinema:releaseYear ?year "
				+ "?x cinema:releaseDate ?date ?x cinema:realisedBy ?director "
				+ "?director cinema:name ?directorName ?x cinema:producedBy ?producer ?producer cinema:name ?producerName"
				+ "?x cinema:affiche ?affiche ?x cinema:synopsis ?synopsis ?x rdf:type cinema:Film}";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				getFilmDescription(result, m);
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<HashMap<String, String>> getFilmByVersion(String version) {
		List<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT * WHERE { ?x cinema:version "
				+ "\""
				+ version
				+ "\""
				+ " "
				+ "?x cinema:name ?name ?x cinema:duration ?duration ?x cinema:version ?version"
				+ "?x cinema:country ?country ?x cinema:rating ?rating ?x cinema:releaseYear ?year "
				+ "?x cinema:releaseDate ?date ?x cinema:realisedBy ?director "
				+ "?director cinema:name ?directorName ?x cinema:producedBy ?producer ?producer cinema:name ?producerName"
				+ "?x cinema:affiche ?affiche ?x cinema:synopsis ?synopsis ?x rdf:type cinema:Film}";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				getFilmDescription(result, m);
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<HashMap<String, String>> getFilmByWord(String word) {
		List<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT distinct * WHERE { { ?x cinema:name ?name ?x rdf:type cinema:Film ?x cinema:duration ?duration ?x cinema:version ?version"
				+ "?x cinema:country ?country ?x cinema:rating ?rating ?x cinema:releaseYear ?year "
				+ "?x cinema:releaseDate ?date ?x cinema:realisedBy ?director "
				+ "?director cinema:name ?directorName ?x cinema:producedBy ?producer ?producer cinema:name ?producerName"
				+ "?x cinema:affiche ?affiche ?x cinema:synopsis ?synopsis ?x rdf:type cinema:Film"
				+ " FILTER regex(?name,"
				+ "\""
				+ word
				+ "\","
				+ "\"i\""
				+ ")} UNION "
				+ "{  ?x cinema:name ?name ?x rdf:type cinema:Film ?x cinema:hasActor ?actor ?actor cinema:name ?actorName?x cinema:duration ?duration "
				+ "?x cinema:country ?country ?x cinema:rating ?rating ?x cinema:releaseYear ?year "
				+ "?x cinema:releaseDate ?date ?x cinema:realisedBy ?director ?x cinema:version ?version"
				+ "?director cinema:name ?directorName ?x cinema:producedBy ?producer ?producer cinema:name ?producerName"
				+ "?x cinema:affiche ?affiche ?x cinema:synopsis ?synopsis ?x rdf:type cinema:Film"
				+ " FILTER regex(?actorName,"
				+ "\""
				+ word
				+ "\","
				+ "\"i\""
				+ ")}}";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				getFilmDescription(result, m);
			}
		} catch (EngineException e) {
		}
		return result;
	}

	private void getFilmDescription(List<HashMap<String, String>> result,
			Mapping m) throws EngineException {
		HashMap<String, String> film = new HashMap<String, String>();
		IDatatype filmName = (IDatatype) m.getValue("?name");
		film.put("filmName", filmName.getLabel());
		IDatatype duration = (IDatatype) m.getValue("?duration");
		film.put("duration", duration.getLabel());
		IDatatype country = (IDatatype) m.getValue("?country");
		film.put("country", country.getLabel());
		IDatatype affiche = (IDatatype) m.getValue("?affiche");
		film.put("affiche", affiche.getLabel());
		IDatatype synopsis = (IDatatype) m.getValue("?synopsis");
		film.put("synopsis", synopsis.getLabel());
		IDatatype version = (IDatatype) m.getValue("?version");
		film.put("version", version.getLabel());

		// get the actors of the given film
		String query1 = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#> "
				+ "SELECT ?actorName WHERE {?x cinema:name "
				+ "\""
				+ filmName.getLabel()
				+ "\""
				+ " ?x cinema:hasActor ?actor ?actor cinema:name ?actorName}";
		Mappings map1 = this.webSemanticService.getExec().query(query1);
		int i = 0;
		for (Mapping m1 : map1) {
			IDatatype actor = (IDatatype) m1.getValue("?actorName");
			film.put("actor" + i, actor.getLabel());
			i++;
		}

		IDatatype rating = (IDatatype) m.getValue("?rating");
		film.put("rating", rating.getLabel());
		IDatatype year = (IDatatype) m.getValue("?year");
		film.put("year", year.getLabel());
		IDatatype date = (IDatatype) m.getValue("?date");
		film.put("date", date.getLabel());
		IDatatype director = (IDatatype) m.getValue("?directorName");
		film.put("directorName", director.getLabel());
		IDatatype producer = (IDatatype) m.getValue("?producerName");
		film.put("producerName", producer.getLabel());

		// get the genre of the given film
		String query2 = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT ?genre WHERE { ?x cinema:name"
				+ "\""
				+ filmName.getLabel() + "\"" + " ?x cinema:genre ?genre}";
		Mappings map2 = this.webSemanticService.getExec().query(query2);
		int j = 0;
		for (Mapping m2 : map2) {
			IDatatype genre = (IDatatype) m2.getValue("?genre");
			film.put("genre" + j, genre.getLabel());
			j++;
		}

		result.add(film);
	}

	@Override
	public List<HashMap<String, String>> getFilmByPrize(String prize) {
		List<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT DISTINCT ?x WHERE {"
				+ " ?x cinema:name ?name ?x rdf:type cinema:Film ?x cinema:duration ?duration ?x cinema:version ?version"
				+ "?x cinema:country ?country ?x cinema:rating ?rating ?x cinema:releaseYear ?year "
				+ "?x cinema:releaseDate ?date ?x cinema:realisedBy ?director "
				+ "?director cinema:name ?directorName ?x cinema:producedBy ?producer ?producer cinema:name ?producerName"
				+ "?x cinema:affiche ?affiche ?x cinema:synopsis ?synopsis ?x rdf:type cinema:Film"
				+ "?x cinema:hasActor ?actor ?actor rdf:type cinema:Actor  {?actor cinema:hasPrize ?prize} UNION {?x cinema:hasPrize ?prize }   ?prize cinema:name "
				+ "\"" + prize + "\"" + "}";
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				getFilmDescription(result, m);
			}
		} catch (EngineException e) {
		}
		return result;
	}

	@Override
	public List<HashMap<String, String>> findFilms(String genre,
			String country, String prize, String language, String date,
			String version) {

		if (genre.isEmpty() | genre.equalsIgnoreCase("genre")) {
			genre = "?genre";
		} else
			genre = "\"" + genre + "\"";

		if (country.isEmpty() | country.equalsIgnoreCase("pays")) {
			country = "?country";
		} else
			country = "\"" + country + "\"";

		if (prize.isEmpty() | prize.equalsIgnoreCase("oscar")) {
			prize = "?prize";
		} else
			prize = "\"" + prize + "\"";

		if (language.isEmpty() | language.equalsIgnoreCase("langue")) {
			language = "?language";
		} else
			language = "\"" + language + "\"";

		if (date.isEmpty() | date.equalsIgnoreCase("date")) {
			date = "?year";
		} else
			date = "\"" + date + "\"";

		if (version.isEmpty() | version.equalsIgnoreCase("version")) {
			version = "?version";
		} else
			version = "\"" + version + "\"";

		List<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
		String query = "prefix cinema: <http://www.tpwebsemantique.fr/2013/01/cinema.rdfs#>"
				+ "SELECT DISTINCT ?x WHERE { ?x cinema:genre "
				+ genre
				+ " ?x cinema:country "
				+ country
				+ " ?x cinema:version "
				+ version
				+ "?x cinema:name ?name "
				+ "?x cinema:language "
				+ language
				+ "?x cinema:duration ?duration "
				+ "?x cinema:rating ?rating "
				+ "?x cinema:releaseYear "
				+ date
				+ "?x cinema:releaseDate ?date "
				+ "?x cinema:realisedBy ?director ?x cinema:country ?country "
				+ "?director cinema:name ?directorName "
				+ "?x cinema:producedBy ?producer "
				+ "?producer cinema:name ?producerName"
				+ "?x cinema:affiche ?affiche ?x cinema:version ?version"
				+ " ?x cinema:synopsis ?synopsis "
				+ "?x rdf:type cinema:Film "
				+ "?x cinema:hasActor ?actor ?x cinema:releaseYear ?year"
				+ "?actor rdf:type cinema:Actor "
				+ " OPTIONAL { ?x cinema:hasPrize ?prize  ?prize cinema:name "
				+ prize + "}}";
		//
		// + "UNION {?x cinema:hasPrize ?prize }   "
		// + "?prize cinema:name " + prize
		try {
			Mappings map = this.webSemanticService.getExec().query(query);
			for (Mapping m : map) {
				getFilmDescription(result, m);
			}
		} catch (EngineException e) {
			System.out.println(e);
		}
		return result;
	}

}
